package com.etong.frame.directive.factory;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.etong.frame.directive.Directive;
import com.etong.frame.directive.DirectiveConfig;
import com.etong.frame.directive.GroupConfig;
import com.etong.frame.directive.GroupDirective;
import com.etong.frame.directive.checker.CheckerConfig;
import com.etong.frame.directive.checker.CheckerFactory;
import com.etong.frame.directive.checker.CheckerGroup;
import com.etong.frame.directive.checker.impl.CheckerFactoryImpl;
import com.etong.frame.directive.deliver.DeliverConfig;
import com.etong.frame.directive.deliver.DeliverFactory;
import com.etong.frame.directive.deliver.DeliverGroup;
import com.etong.frame.directive.deliver.impl.DeliverFactoryImpl;

public class DirectiveManager {
	protected static final Logger logger = LoggerFactory
			.getLogger(DirectiveManager.class);

	public final static String KEY_CHECKER_NAME = "checker_name";
	public final static String KEY_CHECKER_EXPR = "checker_expr";
	public final static String KEY_DELIVER_NAME = "deliver_name";
	public final static String KEY_DELIVER_EXPR = "deliver_expr";

	// 组配置
	protected Map<String, List<GroupConfig>> groupConfigs = new HashMap<String, List<GroupConfig>>();
	// 组命令
	protected Map<String, GroupDirective> groupDirectives = new HashMap<String, GroupDirective>();
	// 命令集
	protected Map<String, Directive> directives = new HashMap<String, Directive>();
	//
	private List<DirectiveLoader> directiveLoaders = new ArrayList<DirectiveLoader>();
	// 检查器
	private Map<String, CheckerGroup> checkerGroups = new HashMap<String, CheckerGroup>();
	// 检查器配置
	private Map<String, CheckerConfig> checkerConfigs = new HashMap<String, CheckerConfig>();
	// 分发器
	private Map<String, DeliverGroup> deliverGroups = new HashMap<String, DeliverGroup>();
	// 分发器配置
	private Map<String, DeliverConfig> deliverConfigs = new HashMap<String, DeliverConfig>();
	// 分发器工厂
	private DeliverFactory deliverFactory = new DeliverFactoryImpl();
	// 检查器工厂
	private CheckerFactory checkerFactory = new CheckerFactoryImpl();

	/**
	 * @Title : createDelivers
	 * @Description : 创建分发器
	 * @params
	 * @param checkerMaps
	 * @return 设定文件
	 * @return boolean 返回类型
	 * @throws
	 */
	public boolean createDelivers(List<Map<String, Object>> checkerMaps) {
		for (Map<String, Object> checkerMap : checkerMaps) {
			addDeliverConfig(checkerMap);
		}

		for (String groupName : deliverConfigs.keySet()) {
			DeliverConfig deliverConfig = deliverConfigs.get(groupName);
			DeliverGroup deliverGroup = deliverFactory
					.createDeliver(deliverConfig);
			deliverGroups.put(groupName, deliverGroup);
		}

		return true;
	}

	/**
	 * @Title : getDeliverGroup
	 * @Description : 获取分发器组
	 * @params
	 * @param name
	 * @return 设定文件
	 * @return DeliverGroup 返回类型
	 * @throws
	 */
	public DeliverGroup getDeliverGroup(String name) {
		return deliverGroups.get(name);
	}

	/**
	 * @Title : addDeliverConfig
	 * @Description : 添加分发器配置
	 * @params
	 * @param checkerMap
	 *            设定文件
	 * @return void 返回类型
	 * @throws
	 */
	protected void addDeliverConfig(Map<String, Object> checkerMap) {
		String checkerName = (String) checkerMap.get(KEY_DELIVER_NAME);
		String checkerExpr = (String) checkerMap.get(KEY_DELIVER_EXPR);

		DeliverConfig deliverConfig = null;
		if (deliverConfigs.containsKey(checkerName)) {
			deliverConfig = deliverConfigs.get(checkerName);
		} else {
			deliverConfig = new DeliverConfig();
			deliverConfigs.put(checkerName, deliverConfig);
		}
		deliverConfig.addExpr(checkerExpr);
	}

	/**
	 * @Title : createCheckers
	 * @Description : 创建检查器
	 * @params
	 * @param checkerMaps
	 * @return 设定文件
	 * @return boolean 返回类型
	 * @throws
	 */
	public boolean createCheckers(List<Map<String, Object>> checkerMaps) {
		for (Map<String, Object> checkerMap : checkerMaps) {
			addCheckerConfig(checkerMap);
		}

		for (String checkerName : checkerConfigs.keySet()) {
			CheckerConfig checkerConfig = checkerConfigs.get(checkerName);
			CheckerGroup checkerGroup = checkerFactory
					.createChecker(checkerConfig);
			checkerGroups.put(checkerName, checkerGroup);
		}

		return true;
	}

	/**
	 * @Title : addCheckerConfig
	 * @Description : 添加配置
	 * @params
	 * @param checkerMap
	 *            设定文件
	 * @return void 返回类型
	 * @throws
	 */
	protected void addCheckerConfig(Map<String, Object> checkerMap) {
		String checkerName = (String) checkerMap.get(KEY_CHECKER_NAME);

		CheckerConfig checkerConfig;
		if (checkerConfigs.containsKey(checkerName)) {
			checkerConfig = checkerConfigs.get(checkerName);
		} else {
			checkerConfig = new CheckerConfig();
			checkerConfigs.put(checkerName, checkerConfig);
		}
		checkerConfig.addCheckerMap(checkerMap);
	}

	/**
	 * @Title : addDirectiveLoader
	 * @Description : 添加指令加载器
	 * @params
	 * @param loader
	 *            设定文件
	 * @return void 返回类型
	 * @throws
	 */
	public void addDirectiveLoader(DirectiveLoader loader) {
		this.directiveLoaders.add(loader);
	}

	/**
	 * @Title : rebuildDirectives
	 * @Description : 重建所有指令
	 * @params
	 * @return 设定文件
	 * @return boolean 返回类型
	 * @throws
	 */
	public boolean rebuildDirectives() {
		for (DirectiveLoader loader : this.getDirectiveLoaders()) {
			loader.createDirecitives(this);
		}
		return true;
	}

	/**
	 * @Title : createDirectives
	 * @Description : 加载指令，访问者模式，指令配置可在访问具体实现类中指定
	 * @params
	 * @return 设定文件
	 * @return boolean 返回类型
	 * @throws
	 */
	public boolean createDirectives(DirectiveLoader loader) {
		this.directiveLoaders.add(loader);
		return loader.createDirecitives(this);
	}

	/**
	 * @Title : createDirectives
	 * @Description : 创建指令信息
	 * @params
	 * @param directiveConfigs
	 * @param groupDirectiveConfigs
	 * @return 设定文件
	 * @return boolean 返回类型
	 * @throws
	 */
	public boolean createDirectives(List<DirectiveConfig> directiveConfigs,
			DirectiveFactory directiveFactory) {

		// 创建指令
		for (DirectiveConfig directiveConfig : directiveConfigs) {
			CheckerGroup checker = getCheckerGroup(directiveConfig
					.getOutputChecker());

			Directive directive = directiveFactory.createDirective(
					directiveConfig, checker);
			if (null != directive) {
				directives.put(directiveConfig.getName(), directive);
				// 单个指令也放在指令组中
				GroupDirective group = new GroupDirective();
				group.addDirective(directive);
				groupDirectives.put(directiveConfig.getName(), group);
			}
		}

		return false;
	}

	/**
	 * @Title : addGroupConfig
	 * @Description : 将配置添加分组的配置列表中
	 * @params
	 * @param groupConfig
	 *            设定文件
	 * @return void 返回类型
	 * @throws
	 */
	protected void addGroupConfig(GroupConfig groupConfig) {
		String group = groupConfig.getGroup_name();
		List<GroupConfig> configList = null;

		if (!this.groupConfigs.containsKey(group)) {
			configList = new ArrayList<GroupConfig>();
			this.groupConfigs.put(group, configList);
		} else {
			configList = groupConfigs.get(group);
		}
		configList.add(groupConfig);
	}

	/**
	 * @Title : createGroupDirectives
	 * @Description : 创建组命令
	 * @params
	 * @param groupConfigList
	 * @return 设定文件
	 * @return boolean 返回类型
	 * @throws
	 */
	public boolean createGroupDirectives(List<GroupConfig> groups) {

		// 初始化组配置信息
		for (GroupConfig groupConfig : groups) {
			addGroupConfig(groupConfig);
		}

		// 初始化指令组
		for (String groupName : this.groupConfigs.keySet()) {
			logger.info("Init group:" + groupName);

			// 创建组对象，并设置组配置信息
			GroupDirective groupDirective = new GroupDirective();
			groupDirective.setGroupConfigs(this.groupConfigs.get(groupName));

			// 将指令添加到组对象中
			for (GroupConfig groupConfig : groupDirective.getGroupConfigs()) {
				String name = groupConfig.getDirective();
				Directive directive = directives.get(name);
				// 将指令添加到group中
				if (null != directive) {
					// 指令包装器
					DirectiveWrapper wrapper = new DirectiveWrapper(directive,
							groupConfig);

					// checkerGroup
					String checker = groupConfig.getOutput_checker();
					if (null != checker && !checker.isEmpty()) {
						wrapper.setCheckerGroup(this.getCheckerGroup(checker));
						logger.info("Add checker to directive :" + checker
								+ "-" + wrapper.getName());
					}
					groupDirective.addDirective(wrapper);
				} else {
					logger.warn("Directive no found:" + name);
				}
			}
			// 组操作会覆盖普通操作
			groupDirectives.put(groupName, groupDirective);
		}
		return true;
	}

	/**
	 * @Title : getGroupDirective
	 * @Description : 根据指令组名获取获得指令组对象
	 * @params
	 * @param groupName
	 * @return 设定文件
	 * @return GroupDirective 返回类型
	 * @throws
	 */
	public GroupDirective getGroupDirective(String groupName) {
		if (null == groupName || groupName.isEmpty()) {
			logger.error("Group directive name empty");
			return null;
		}

		GroupDirective groupDirective = groupDirectives.get(groupName);
		if (null == groupDirective) {
			logger.error("No group directive found:" + groupName);
			return null;
		}
		return groupDirective;
	}

	/**
	 * @Title : createDirective
	 * @Description : 创建指令
	 * @params
	 * @param directiveConfig
	 * @param executor
	 * @return 设定文件
	 * @return Directive 返回类型
	 * @throws
	 */
	public Directive createDirective(DirectiveConfig directiveConfig,
			DirectiveFactory directiveFactory) {
		CheckerGroup checker = getCheckerGroup(directiveConfig
				.getOutputChecker());
		return directiveFactory.createDirective(directiveConfig, checker);
	}

	/**
	 * @Title : getGroupDirectives
	 * @Description : 获取所有组指令信息
	 * @params
	 * @return 设定文件
	 * @return Map<String,GroupDirective> 返回类型
	 * @throws
	 */
	public Map<String, GroupDirective> getGroupDirectives() {
		return this.groupDirectives;
	}

	/**
	 * @Title : getCheckerGroup
	 * @Description : 获取检查器
	 * @params
	 * @param name
	 * @return 设定文件
	 * @return CheckerGroup 返回类型
	 * @throws
	 */
	public CheckerGroup getCheckerGroup(String name) {
		return checkerGroups.get(name);
	}

	public List<DirectiveLoader> getDirectiveLoaders() {
		return directiveLoaders;
	}

	public void setDirectiveLoaders(List<DirectiveLoader> directiveLoaders) {
		this.directiveLoaders = directiveLoaders;
	}

	public CheckerFactory getCheckerFactory() {
		return checkerFactory;
	}

	public void setCheckerFactory(CheckerFactory checkerFactory) {
		this.checkerFactory = checkerFactory;
	}

}
